#include "package.h"
#include "cJSON.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/***************************************************************************/
// Json包的字段名称, 字段名不可随意修改
static const DeviceItemsKey g_deviceItemsKey = {"device_id", "sensor", "timestamp", "times", "control"};
static const CtrItemsKey g_ctrItemsKey = {"ctrdevice_id", "status", "ctr", "resultl"};
static const SensorItems g_sensorItems = {"et", "eh", "pm25", "pm10", "o2", "wt", "ph", "do2", "ws", "wd", "td", "cdt"};
static const SwitchStatusItems g_switchStatusItems = {"S_No", "status", "timestamp"};

/* 全局变量数据 */
// 设备值初始化, 设置ID号, 心跳包上传次数为0, 时间戳为0等
DeviceItemsValue g_deviceItemsValue = {"60989ac0dc3d9af2c91dc293", 0, 0};
// 传感器数据初始化为0
SensorData g_sensorData = {0};

// 所有控制设备(继电器)的id号, 每个控制设备(继电器)独自一个号
#define NUM_OF_CTR_ID 1
static const char *g_ctrdevice_id[NUM_OF_CTR_ID] = {"60989ac0dc3d9af2c91dc293"};
//#define NUM_OF_CTR_ID 4
// static const char g_ctrdevice_id[NUM_OF_CTR_ID] =
// {"60989ac0dc3d9af2c91dc293","60989ac0dc3d9af2c91dc293","60989ac0dc3d9af2c91dc293","60989ac0dc3d9af2c91dc293"};
/***************************************************************************/

/* cJson init, 必须先使用该函数进行初始化*/
int CJson_hook_init(void)
{
    cJSON_Hooks cJSON_hook;

    cJSON_hook.malloc_fn = (void *(*)(size_t sz))malloc;
    cJSON_hook.free_fn = free;

    cJSON_InitHooks(&cJSON_hook);

    return 0;
}

/* 将传感器数据打包成Json对象, 如果失败, return NULL */
// 输入 data : 传感器数据结构体
// 输出 : Json对象
static cJSON *PackSensorData2Json(SensorData *data)
{
    cJSON *json = cJSON_CreateObject();
    if (!json) {
        cJSON_Delete(json);
        return NULL;
    }

    cJSON_AddNumberToObject(json, g_sensorItems.et, data->et);
    cJSON_AddNumberToObject(json, g_sensorItems.eh, data->eh);
    cJSON_AddNumberToObject(json, g_sensorItems.pm25, data->pm25);
    cJSON_AddNumberToObject(json, g_sensorItems.pm10, data->pm10);
    cJSON_AddNumberToObject(json, g_sensorItems.o2, data->o2);
    cJSON_AddNumberToObject(json, g_sensorItems.wt, data->wt);
    cJSON_AddNumberToObject(json, g_sensorItems.ph, data->ph);
    cJSON_AddNumberToObject(json, g_sensorItems.do2, data->do2);
    cJSON_AddNumberToObject(json, g_sensorItems.ws, data->ws);
    cJSON_AddStringToObject(json, g_sensorItems.wd, data->wd);
    cJSON_AddNumberToObject(json, g_sensorItems.td, data->td);
    cJSON_AddNumberToObject(json, g_sensorItems.cdt, data->cdt);

    return json;
}

/* 将数据打包成上行Json字符串, 如果失败, return NULL; 使用完成记得free */
// 输入 itemValue : 设备信息, 主要取其ID号与时间戳
// 输入 data : 传感器数据结构体
char *PackData2UpLoadJsonString(DeviceItemsValue *itemValue, SensorData *data)
{
    cJSON *json = cJSON_CreateObject();
    if (!json) {
        cJSON_Delete(json);
        return NULL;
    }

    cJSON_AddStringToObject(json, g_deviceItemsKey.id, itemValue->id);
    cJSON_AddItemToObject(json, g_deviceItemsKey.sensor, PackSensorData2Json(data));
    // 如果不需要时间戳字段请注释下行代码
    cJSON_AddNumberToObject(json, g_deviceItemsKey.timestamp, itemValue->timestamp);

    /* 将Json对象转化为string */
    char *upLoadStr = cJSON_PrintUnformatted(json);
    if (!upLoadStr) {
        cJSON_Delete(json);
        return NULL;
    }

    /* 删除Json对象 */
    cJSON_Delete(json);

    return upLoadStr;
}

/* 生成传感器心跳包字符串, 如果失败, return NULL; 使用完成记得free */
// 输入 itemValue : 设备信息, 主要取其ID号与时间戳
char *CreatSensorHeartbeatPacket(DeviceItemsValue *itemValue)
{
    cJSON *json = cJSON_CreateObject();
    if (!json) {
        cJSON_Delete(json);
        return NULL;
    }

    cJSON_AddStringToObject(json, g_deviceItemsKey.id, itemValue->id);
    cJSON_AddNumberToObject(json, g_deviceItemsKey.times, itemValue->times);
    // 如果需要时间戳字段请取消注释
    // cJSON_AddNumberToObject(json, g_deviceItemsKey.timestamp, itemValue->timestamp);

    /* 将Json对象转化为string */
    char *heartbeatStr = cJSON_PrintUnformatted(json);
    if (!heartbeatStr) {
        cJSON_Delete(json);
        return NULL;
    }

    /* 删除Json对象 */
    cJSON_Delete(json);

    return heartbeatStr;
}

/* 控制设备心跳包字符串, 如果失败, return NULL; 使用完成记得free */
// 输入 itemValue : 控制设备(继电器)信息, 主要取其ID号与继电器状态
char *CreatCtrHeartbeatPacket(CtrItemsValue *itemValue)
{
    cJSON *json = cJSON_CreateObject();
    if (!json) {
        cJSON_Delete(json);
        return NULL;
    }

    cJSON_AddStringToObject(json, g_ctrItemsKey.ctr_id, itemValue->ctr_id);
    cJSON_AddNumberToObject(json, g_ctrItemsKey.status, itemValue->status);

    /* 将Json对象转化为string */
    char *ctrHeartbeatStr = cJSON_PrintUnformatted(json);
    if (!ctrHeartbeatStr) {
        cJSON_Delete(json);
        return NULL;
    }

    /* 删除Json对象 */
    cJSON_Delete(json);

    return ctrHeartbeatStr;
}

/* 控制设备控制结果(控制反馈)字符串, 如果失败, return NULL; 使用完成记得free */
// 输入 itemValue : 控制设备(继电器)信息, 主要取其ID号与控制结果
char *CreatCtrResultPacket(CtrItemsValue *itemValue)
{
    cJSON *json = cJSON_CreateObject();
    if (!json) {
        cJSON_Delete(json);
        return NULL;
    }

    cJSON_AddStringToObject(json, g_ctrItemsKey.ctr_id, itemValue->ctr_id);
    cJSON_AddNumberToObject(json, g_ctrItemsKey.result, itemValue->result);

    /* 将Json对象转化为string */
    char *ctrResultStr = cJSON_PrintUnformatted(json);
    if (!ctrResultStr) {
        cJSON_Delete(json);
        return NULL;
    }

    /* 删除Json对象 */
    cJSON_Delete(json);

    return ctrResultStr;
}

/* 解析下行字符串 */
// 输入 keysValue : 所有控制设备的ID号
// 输入 downStr : 下行字串
// 输入/输出 switchStatus: 前端的控制状态, 0表示关, 1表示开
void ParseCtrString(char *downStr, SwitchStatus *switchStatus)
{
    cJSON *json = cJSON_Parse(downStr);
    if (!json) {
        printf("Error before: [%s]\r\n", cJSON_GetErrorPtr());
        cJSON_Delete(json);
        return;
    }

    for (int i = 0; i < NUM_OF_CTR_ID; i++) {
        if (strcmp(cJSON_GetObjectItem(json, g_ctrItemsKey.ctr_id)->valuestring, g_ctrdevice_id[i]) == 0) {
            /* 通道序号与前面定义的g_ctrdevice_id数组相对应 */
            switchStatus->S_No = i + 1;
            switchStatus->status = cJSON_GetObjectItem(json, g_ctrItemsKey.ctr)->valueint;

            cJSON_Delete(json);
            return;
        }
    }

    printf("The string is not have this ctr device!\r\n");

    cJSON_Delete(json);
}

/**********************************下行*************************************/

/* 解析下行字符串 */
// 输入 itemValue : 设备信息, 主要取其ID号
// 输入 downStr : 下行字串
// 输入/输出 switchStatus : 开关状态结构体, 作为状态返回值
void ParseDownString(DeviceItemsValue *itemValue, char *downStr, SwitchStatus *switchStatus)
{
    cJSON *json = cJSON_Parse(downStr);
    if (!json) {
        printf("Error before: [%s]\r\n", cJSON_GetErrorPtr());
        cJSON_Delete(json);
        return;
    }

    if (strcmp(cJSON_GetObjectItem(json, g_deviceItemsKey.id)->valuestring, itemValue->id) != 0) {
        printf("The string is not for this device!\r\n");
        cJSON_Delete(json);
        return;
    }

    switchStatus->S_No = cJSON_GetObjectItem(json, g_switchStatusItems.S_No)->valueint;
    switchStatus->status = cJSON_GetObjectItem(json, g_switchStatusItems.status)->valueint;
    switchStatus->timestamp = cJSON_GetObjectItem(json, g_switchStatusItems.timestamp)->valueint;

    cJSON_Delete(json);
}

/*
struct tm {
    int tm_sec;       //秒 – 取值区间为[0,59]
    int tm_min;       //分 - 取值区间为[0,59]
    int tm_hour;      //时 - 取值区间为[0,23]
    int tm_mday;      //一个月中的日期 - 取值区间为[1,31]
    int tm_mon;       //月份（从一月开始，0代表一月） - 取值区间为[0,11]
    int tm_year;      //年份，其值等于实际年份减去1900
    int tm_wday;      //星期 –
取值区间为[0,6]，其中0代表星期天，1代表星期一，以此类推 int tm_yday;
//从每年的1月1日开始的天数 –
取值区间为[0,365]，其中0代表1月1日，1代表1月2日，以此类推 int tm_isdst;
//夏令时标识符，实行夏令时的时候，tm_isdst为正。不实行夏令时的进候，tm_isdst为0；不了解情况时，tm_isdst()为负。
};
*/
/* struct tm转时间戳, 时间结构体转时间戳 */
time_t LocalTime2Timestamp(LocalTime *time) { return mktime(time); }

/* 时间戳转struct tm, 时间戳转时间结构体 */
LocalTime *Timestamp2LocalTime(time_t time) { return localtime(&time); }